package com.sunrise.xdoc.dataloader;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.joda.time.LocalTime;
import org.joda.time.YearMonth;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;

import com.sunrise.xdoc.entity.catalog.DonViTinh;
import com.sunrise.xdoc.entity.catalog.LoaiSanPham;
import com.sunrise.xdoc.entity.catalog.SanPham;
import com.sunrise.xdoc.entity.config.Ban;
import com.sunrise.xdoc.entity.config.ChiNhanh;
import com.sunrise.xdoc.entity.config.InternalCode;
import com.sunrise.xdoc.entity.config.KhuVuc;
import com.sunrise.xdoc.entity.contact.KhachHang;
import com.sunrise.xdoc.entity.contact.LoaiKhachHang;
import com.sunrise.xdoc.entity.contact.LoaiNhanVien;
import com.sunrise.xdoc.entity.contact.NhaCungCap;
import com.sunrise.xdoc.entity.contact.NhanVien;
import com.sunrise.xdoc.entity.employee.CaLamViec;
import com.sunrise.xdoc.entity.employee.TraLuong;
import com.sunrise.xdoc.entity.employee.TraLuong.LoaiTraLuong;
import com.sunrise.xdoc.entity.finance.PhieuThanhToan;
import com.sunrise.xdoc.entity.finance.PhieuThanhToan.LoaiThanhToan;
import com.sunrise.xdoc.entity.operator.Function;
import com.sunrise.xdoc.entity.operator.Module;
import com.sunrise.xdoc.entity.operator.Operator;
import com.sunrise.xdoc.entity.operator.Operator.OperatorState;
import com.sunrise.xdoc.entity.operator.OperatorProfile;
import com.sunrise.xdoc.entity.operator.OperatorRole;
import com.sunrise.xdoc.entity.operator.Privilege;
import com.sunrise.xdoc.entity.order.ChiTietDonHang;
import com.sunrise.xdoc.entity.order.DinhMuc;
import com.sunrise.xdoc.entity.order.DonHang;
import com.sunrise.xdoc.entity.store.ChiTietKho;
import com.sunrise.xdoc.entity.store.ChiTietNhapKho;
import com.sunrise.xdoc.entity.store.ChiTietXuatKho;
import com.sunrise.xdoc.entity.store.Kho;
import com.sunrise.xdoc.entity.store.LyDoXuatKho;
import com.sunrise.xdoc.entity.store.PhieuNhapKho;
import com.sunrise.xdoc.entity.store.PhieuXuatKho;
import com.sunrise.xdoc.entity.user.EmployeeProfile;
import com.sunrise.xdoc.entity.user.EmployeeProfile.Sex;
import com.sunrise.xdoc.entity.user.Role;
import com.sunrise.xdoc.entity.user.User;
import com.sunrise.xdoc.helper.DaoHelper;
import com.sunrise.xdoc.service.IInternalCodeService;

/**
 * This dataloader will generate config data, some sample data for development
 * team. Another dataloader for customer will be created later.
 * 
 */
public class XDocDataLoader {
	private static final String CN_HO_CHI_MINH = "CN_HO_CHI_MINH";
	private static ApplicationContext appContext;
	private static DaoHelper daoHelper;
	private static IInternalCodeService internaCodeService;

	public static void main(String[] args) {
		appContext = new ClassPathXmlApplicationContext("/serviceContext.xml");
		daoHelper = (DaoHelper) appContext.getBean("daoHelper");
		internaCodeService = (IInternalCodeService) appContext.getBean("internalCodeService");
		SecurityContextHolder.getContext().setAuthentication(
				new UsernamePasswordAuthenticationToken("dummyUser", "123456"));
		initOrganization();
		initBan();
		initUsers();
		initKhachHang();
		initNhaCungCap();
		initNhanVien();

		initSanPham();
		initDonHang();
		initPhieuThanhToan();
		initKho();
	}

	private static void initNhanVien() {
		CaLamViec ca = new CaLamViec();
		ca.setName("Ca sáng 2->7");
		ca.setStartTime(new LocalTime(7, 0, 0));
		ca.setEndTime(new LocalTime(12, 0, 0));
		daoHelper.getDao(CaLamViec.class).saveOrUpdate(ca);

		LoaiNhanVien loai = new LoaiNhanVien();
		loai.setName("Quản lý");
		loai.setLuongThamKhao(4000000);
		daoHelper.getDao(LoaiNhanVien.class).saveOrUpdate(loai);

		NhanVien nhanVien = new NhanVien();
		nhanVien.setName("Trần Văn A");
		nhanVien.setCmnd("271735619");
		nhanVien.setAddress("64 Ngô Chí Quốc, phường Bình Chiểu, Thủ Đức, HCM");
		nhanVien.setLuongThang(4000000);
		nhanVien.getCaLamViecs().add(ca);
		daoHelper.getDao(NhanVien.class).saveOrUpdate(nhanVien);

		PhieuThanhToan phieuThanhToan1 = new PhieuThanhToan();
		phieuThanhToan1.setLoai(LoaiThanhToan.PHIEU_CHI);
		phieuThanhToan1.setSoTien(-1000000L);
		phieuThanhToan1.setMaNhanVien("admin");
		phieuThanhToan1.setThongTin("Cần tiền đóng học phí");
		daoHelper.getDao(PhieuThanhToan.class).saveOrUpdate(phieuThanhToan1);

		TraLuong tamUng = new TraLuong();
		tamUng.setLoai(LoaiTraLuong.TAM_UNG);
		tamUng.setYearMonth(YearMonth.now());
		tamUng.setNhanVien(nhanVien);
		tamUng.setPhieuThanhToan(phieuThanhToan1);
		daoHelper.getDao(TraLuong.class).saveOrUpdate(tamUng);

		PhieuThanhToan phieuThanhToan2 = new PhieuThanhToan();
		phieuThanhToan2.setLoai(LoaiThanhToan.PHIEU_CHI);
		phieuThanhToan2.setSoTien(-3000000L);
		phieuThanhToan2.setMaNhanVien("admin");
		phieuThanhToan2.setThongTin("Trả lương cuối tháng");
		daoHelper.getDao(PhieuThanhToan.class).saveOrUpdate(phieuThanhToan2);

		TraLuong tatToan = new TraLuong();
		tatToan.setLoai(LoaiTraLuong.TAT_TOAN);
		tatToan.setYearMonth(YearMonth.now());
		tatToan.setNhanVien(nhanVien);
		tatToan.setPhieuThanhToan(phieuThanhToan2);
		daoHelper.getDao(TraLuong.class).saveOrUpdate(tatToan);
	}

	private static void initNhaCungCap() {
		NhaCungCap nhaCungCap = new NhaCungCap();
		nhaCungCap.setName("Công ty Cà phê Trung Nguyên");
		nhaCungCap.setAddress("82-84 Bùi Thị Xuân, Q.1 Tp. HCM, Việt Nam");
		nhaCungCap.setEmail("office@trungnguyen.com.vn");
		nhaCungCap.setPhone("(84.8) 39251852");
		nhaCungCap.setFax("(84.8) 39251848");
		daoHelper.getDao(NhaCungCap.class).saveOrUpdate(nhaCungCap);

	}

	private static void initKhachHang() {
		LoaiKhachHang loai = new LoaiKhachHang();
		loai.setName("VIP");
		loai.setTongGiaTriDonHang(4000000);
		daoHelper.getDao(LoaiKhachHang.class).saveOrUpdate(loai);
		KhachHang khachHang = new KhachHang();
		khachHang.setLoai(loai);
		khachHang.setName("Phạm Công B");
		khachHang.setAddress("64/7 Ngô Chí Quốc, phường Bình Chiểu, quận Thủ Đức, HCM");
		khachHang.setCmnd("271735618");
		khachHang.setEmail("congbangmm83@gmail.com");
		daoHelper.getDao(KhachHang.class).saveOrUpdate(khachHang);
	}

	private static void initKho() {
		Kho kho = new Kho();
		kho.setChiNhanh(getChiNhanh());
		kho.setCode("KHO_1");
		kho.setName("Kho 1");
		kho.setThongTin("Đặt tại cửa hàng chính. Anh B làm thủ kho.");
		daoHelper.getDao(Kho.class).saveOrUpdate(kho);

		ChiTietKho chiTiet = new ChiTietKho();
		chiTiet.setKho(kho);
		SanPham sanPham = daoHelper.getDao(SanPham.class).findByCode("CAFE_DA");
		chiTiet.setSanPham(sanPham);
		chiTiet.setSoLuong(100);
		daoHelper.getDao(ChiTietKho.class).saveOrUpdate(chiTiet);

		PhieuNhapKho nhapKho = new PhieuNhapKho();
		nhapKho.setKho(kho);
		nhapKho.setCode("NK0001");
		nhapKho.setNgayTao(new Date());
		nhapKho.setNhaCungCap("Công ty TNHH Trà Sữa Đài Loan");
		nhapKho.setNhanVien("admin");
		daoHelper.getDao(PhieuNhapKho.class).saveOrUpdate(nhapKho);
		ChiTietNhapKho chiTietNhap = new ChiTietNhapKho();
		chiTietNhap.setPhieuNhapKho(nhapKho);
		chiTietNhap.setDonGiaNhap(18000L);
		chiTietNhap.setSanPham(sanPham);
		chiTietNhap.setSoLuong(300);
		daoHelper.getDao(ChiTietNhapKho.class).saveOrUpdate(chiTietNhap);

		PhieuXuatKho xuatKho = new PhieuXuatKho();
		xuatKho.setKho(kho);
		xuatKho.setCode("XK0001");
		xuatKho.setNgayTao(new Date());
		xuatKho.setNhanVien("admin");
		xuatKho.setLyDo(LyDoXuatKho.BAN_HANG);
		daoHelper.getDao(PhieuXuatKho.class).saveOrUpdate(xuatKho);
		ChiTietXuatKho chiTietXuat = new ChiTietXuatKho();
		chiTietXuat.setPhieuXuatKho(xuatKho);
		chiTietXuat.setSanPham(sanPham);
		chiTietXuat.setSoLuong(200);
		daoHelper.getDao(ChiTietXuatKho.class).saveOrUpdate(chiTietXuat);
	}

	private static void initPhieuThanhToan() {
		PhieuThanhToan phieuThu = new PhieuThanhToan();
		phieuThu.setLoai(LoaiThanhToan.PHIEU_THU);
		phieuThu.setMaNhanVien("admin");
		phieuThu.setSoTien(1000000L);
		phieuThu.setThongTin("Thu lại tiền đặt cọc của nhà cung cấp sữa");
		daoHelper.getDao(PhieuThanhToan.class).saveOrUpdate(phieuThu);

		PhieuThanhToan phieuChi = new PhieuThanhToan();
		phieuChi.setLoai(LoaiThanhToan.PHIEU_CHI);
		phieuChi.setMaNhanVien("admin");
		phieuChi.setSoTien(-2000000L);
		phieuChi.setThongTin("Tra luong nhan vien Nguyen Van A thang 1/2013");
		daoHelper.getDao(PhieuThanhToan.class).saveOrUpdate(phieuChi);

	}

	private static void initDonHang() {
		DonHang donHang = new DonHang();
		donHang.getBans().add(daoHelper.getDao(Ban.class).findByCode("A1"));
		donHang.getBans().add(daoHelper.getDao(Ban.class).findByCode("A3"));
		donHang.setCode("DH10000");
		donHang.setMaNhanVienPhucVu("DDD");
		donHang.setThoiGianDatHang(new Date());

		ChiTietDonHang chiTiet = new ChiTietDonHang();
		SanPham sanPham = daoHelper.getDao(SanPham.class).findByCode("CAFE_DA");
		chiTiet.setSanPham(sanPham);
		chiTiet.setDonGia(sanPham.getDonGia());
		chiTiet.setSoLuong(3);
		chiTiet.setDonHang(donHang);
		donHang.setTongGiaSanPham(chiTiet.getDonGia() * 3);
		daoHelper.getDao(DonHang.class).saveOrUpdate(donHang);
		daoHelper.getDao(ChiTietDonHang.class).saveOrUpdate(chiTiet);

		DonHang donHang1 = new DonHang();
		donHang1.getBans().add(daoHelper.getDao(Ban.class).findByCode("A4"));
		donHang1.setCode("DH10001");
		donHang1.setMaNhanVienPhucVu("CBP");
		donHang1.setThoiGianDatHang(new Date());

		ChiTietDonHang chiTiet1 = new ChiTietDonHang();
		SanPham sanPham1 = daoHelper.getDao(SanPham.class).findByCode("CAFE_SUA_DA");
		chiTiet1.setSanPham(sanPham1);
		chiTiet1.setDonGia(sanPham1.getDonGia());
		chiTiet1.setSoLuong(3);
		chiTiet1.setDonHang(donHang1);
		donHang1.setTongGiaSanPham(chiTiet1.getDonGia() * 3);
		daoHelper.getDao(DonHang.class).saveOrUpdate(donHang1);
		daoHelper.getDao(ChiTietDonHang.class).saveOrUpdate(chiTiet1);
	}

	private static void initSanPham() {
		ChiNhanh chiNhanh = getChiNhanh();
		DonViTinh dvt = createDonViTinh("LY", "Ly", chiNhanh);
		DonViTinh dvt2 = createDonViTinh("LON", "Lon 330", chiNhanh);

		LoaiSanPham cafe = createLoaiSanPham("CAFE", "Cà phê", chiNhanh);
		LoaiSanPham kem = createLoaiSanPham("KEM", "Kem", chiNhanh);
		LoaiSanPham giaiKhat = createLoaiSanPham("GIAI_KHAT", "Giải khát", chiNhanh);

		String code = "CAFE_DA";
		String name = "Cà phê đá";
		long donGia = 20000L;
		String thongTin = "50g cà phê pha với 100g đường + 220 ml nước + đá";

		createSanPham(dvt, cafe, code, name, donGia, thongTin);
		createSanPham(dvt, cafe, "CAFE_SUA_DA", "Cà phê sữa đá", 22000L, "");
		createSanPham(dvt, cafe, "CAFE_SUA_NONG", "Cà phê sữa nóng", 25000L, "Thêm 1 ấm trà nóng");
		createSanPham(dvt, cafe, "CAFE_NONG", "Cà phê nóng", 25000L, "Thêm 1 tách trà nóng");
		createSanPham(dvt, cafe, "CAFE_KHONG_DUONG", "Cà không đường", 20000L, "Thêm 1 tách trà nóng");
		createSanPham(dvt, cafe, "CAFE_KEM", "Cà phê kem", 25000L, "");
		createSanPham(dvt, cafe, "CAFE_CAPUCHINO", "Cà phê Capuchino", 35000L, "");
		createSanPham(dvt, cafe, "CAFE_SOCOLA", "Cà phê Sô cô la", 30000L, "");
		createSanPham(dvt, cafe, "CAFE_TRUNG_NGUYEN", "Cà phê Trung nguyên", 25000L, "");
		createSanPham(dvt, cafe, "CAFE_SIRO", "Cà phê Sirô", 30000L, "");

		createSanPham(dvt, kem, "KEM_SUA_TUOI", "Kem sữa tươi", 15000L, "Kem sữa tươi trong bánh cốm");
		createSanPham(dvt, kem, "KEM_SUA_TUYET", "Kem sữa tuyết", 22000L, "Kem sữa đá tuyết");
		createSanPham(dvt, kem, "KEM_SUA_NONG", "Kem sữa nóng", 25000L, "Kem được phủ lớp cốm nóng");
		createSanPham(dvt, kem, "KEM_SUA_SOCOLA", "Kem sữa sô cô la", 25000L, "");
		createSanPham(dvt, kem, "KEM_SUA_DAU", "Kem sữa dâu", 20000L, "Hương vị dâu");
		createSanPham(dvt, kem, "KEM_KHOAI_MON", "Kem khoai môn", 25000L, "");
		createSanPham(dvt, kem, "KEM_SAU_RIENG", "Kem sầu riêng", 35000L, "");
		createSanPham(dvt, kem, "KEM_SIRO", "Kem sirô", 20000L, "");
		createSanPham(dvt, kem, "KEM_BO", "KEM bơ", 25000L, "");
		createSanPham(dvt, kem, "KEM_SUNRISE", "Kem Sunrise", 30000L, "");

		createSanPham(dvt2, giaiKhat, "COCA330", "Cocacola lon", 15000L, "");
		createSanPham(dvt2, giaiKhat, "TRA_BI_DAO", "Trà Bí Đao", 15000L, "");
		createSanPham(dvt2, giaiKhat, "PEPSI", "PEPSI lon", 15000L, "");
		createSanPham(dvt2, giaiKhat, "CAM_EP", "Nước cam ép", 14000L, "");
		createSanPham(dvt, giaiKhat, "CHANH_DA", "Nước đá chanh", 20000L, "");
		createSanPham(dvt, giaiKhat, "BO_NGHIEN", "Bơ nghiền", 25000L, "");
		createSanPham(dvt, giaiKhat, "SINH_TO_DAU", "Sinh tố dâu", 25000L, "");
		createSanPham(dvt, giaiKhat, "SINH_TO_SA_PO_CHE", "Sinh tố Sa Pô Chê", 25000L, "");
		createSanPham(dvt, giaiKhat, "NUOC_NHA", "Nước nhãn", 20000L, "");
		createSanPham(dvt, giaiKhat, "TRA_SUA_TRAN_CHAU", "Trà sữa Trân Châu", 25000L, "");

	}

	private static ChiNhanh getChiNhanh() {
		ChiNhanh chiNhanh = daoHelper.getDao(ChiNhanh.class).findByCode(CN_HO_CHI_MINH);
		return chiNhanh;
	}

	private static void createSanPham(DonViTinh dvt, LoaiSanPham cafe, String code, String name, long donGia,
			String thongTin) {
		SanPham sanPham = new SanPham();
		sanPham.setLoaiSP(cafe);
		sanPham.setCode(code);
		sanPham.setName(name);
		sanPham.setActive(true);
		sanPham.setDonViTinh(dvt);
		sanPham.setDonGia(donGia);
		sanPham.setThongTin(thongTin);
		daoHelper.getDao(SanPham.class).saveOrUpdate(sanPham);

		DinhMuc dinhMuc = new DinhMuc();
		dinhMuc.setSanPham(sanPham);
		dinhMuc.setDinhMucBan(300);
		dinhMuc.setConLai(50);
		daoHelper.getDao(DinhMuc.class).saveOrUpdate(dinhMuc);
	}

	private static LoaiSanPham createLoaiSanPham(String code, String name, ChiNhanh chiNhanh) {
		LoaiSanPham cafe = new LoaiSanPham();
		cafe.setChiNhanh(chiNhanh);
		cafe.setCode(code);
		cafe.setName(name);
		daoHelper.getDao(LoaiSanPham.class).saveOrUpdate(cafe);
		return cafe;
	}

	private static DonViTinh createDonViTinh(String code, String name, ChiNhanh chiNhanh) {
		DonViTinh dvt = new DonViTinh();
		dvt.setChiNhanh(daoHelper.getDao(ChiNhanh.class).findByCode(CN_HO_CHI_MINH));
		dvt.setCode(code);
		dvt.setName(name);
		daoHelper.getDao(DonViTinh.class).saveOrUpdate(dvt);
		return dvt;
	}

	private static void initBan() {
		createKhuVuc("Tang A", 1);
		createKhuVuc("Tang B", 7);
	}

	private static void createKhuVuc(String khuVucName, int startBanNumber) {
		KhuVuc khuVuc = new KhuVuc();
		khuVuc.setCode(khuVucName);
		khuVuc.setName(khuVucName);
		khuVuc.setChiNhanh(daoHelper.getDao(ChiNhanh.class).findByCode(CN_HO_CHI_MINH));
		daoHelper.getDao(KhuVuc.class).saveOrUpdate(khuVuc);

		for (int i = 0; i < 6; i++) {
			Ban ban = new Ban();
			ban.setCode("A" + startBanNumber);
			ban.setName("A" + startBanNumber++);
			ban.setSoChoNgoi(4);
			ban.setKhuVuc(khuVuc);
			daoHelper.getDao(Ban.class).saveOrUpdate(ban);
		}
	}

	private static void initOrganization() {
		ChiNhanh org = new ChiNhanh();
		org.setCode(CN_HO_CHI_MINH);
		org.setName("Chi nhánh Hồ Chí Minh");
		org.setAddress("345/41/5 Phan Văn Trị, quận Bình Thạnh, tp Hồ Chí Minh");
		org.setPhone("0909123456");
		daoHelper.getDao(ChiNhanh.class).saveOrUpdate(org);
	}

	private static void initUsers() {
		User u = new User();
		u.setUsername("php");
		u.setPassword("123456");
		u.setCode("userCode");

		// TODO: This entity Role will be removed.
		Role r = new Role(Role.ADMIN);
		r.setCode("roleCode");
		Set<Role> roles = new HashSet<>();
		roles.add(r);

		u.setRoles(roles);
		daoHelper.getDao(User.class).saveOrUpdate(u);

		// TODO: This entity EmployeeProfile will be removed.
		EmployeeProfile oldProfile = new EmployeeProfile();
		oldProfile.setFirstName("Nguyen");
		// profile.setMiddleName("Van");
		oldProfile.setLastName("B");
		oldProfile.setSex(Sex.MAN);
		oldProfile.setUniverstity(daoHelper.getDao(InternalCode.class).findByCode("UNIVERSITY/KHTN-HCM"));
		daoHelper.getDao(EmployeeProfile.class).saveOrUpdate(oldProfile);

		Operator operator = new Operator();
		operator.setUser(u);
		operator.setState(OperatorState.ACTIVE);
		operator.setChiNhanh(getChiNhanh());
		daoHelper.getDao(Operator.class).saveOrUpdate(operator);

		OperatorProfile profile = new OperatorProfile();
		profile.setCode("FULL_ACCESS");
		profile.setName("Toàn quyền hệ thống");
		profile.setActive(true);
		daoHelper.getDao(OperatorProfile.class).saveOrUpdate(profile);

		OperatorRole opRole = new OperatorRole();
		opRole.setOperator(operator);
		opRole.setProfile(profile);
		daoHelper.getDao(OperatorRole.class).saveOrUpdate(opRole);

		Module module = new Module();
		module.setCode("BAN_HANG");
		module.setName("Bán hàng");
		module.setActive(true);
		daoHelper.getDao(Module.class).saveOrUpdate(module);

		Function function = new Function();
		function.setCode("XEM_LIST_HOA_DON");
		function.setName("Xem danh sách hóa đơn");
		function.setActive(true);
		function.setModule(module);
		function.setPossibleMode("RU"); // read and update
		daoHelper.getDao(Function.class).saveOrUpdate(function);

		Privilege privilege = new Privilege();
		privilege.setFunction(function);
		privilege.setProfile(profile);
		privilege.setPossibleMode("RU");
		daoHelper.getDao(Privilege.class).saveOrUpdate(privilege);

		Module module2 = new Module();
		module2.setCode("KHO");
		module2.setName("Kho");
		module2.setActive(true);
		daoHelper.getDao(Module.class).saveOrUpdate(module2);

		Function function2 = new Function();
		function2.setCode("NHAP_KHO");
		function2.setName("Nhập kho");
		function2.setActive(true);
		function2.setModule(module2);
		function2.setPossibleMode("CRUDE"); // read and update
		daoHelper.getDao(Function.class).saveOrUpdate(function2);

		Privilege privilege2 = new Privilege();
		privilege2.setFunction(function2);
		privilege2.setProfile(profile);
		privilege2.setPossibleMode("CRUDE");
		daoHelper.getDao(Privilege.class).saveOrUpdate(privilege2);

		Function function3 = new Function();
		function3.setCode("XUAT_KHO");
		function3.setName("Xuất kho");
		function3.setActive(true);
		function3.setModule(module2);
		function3.setPossibleMode("CRUDE"); // read and update
		daoHelper.getDao(Function.class).saveOrUpdate(function3);

		Privilege privilege3 = new Privilege();
		privilege3.setFunction(function3);
		privilege3.setProfile(profile);
		privilege3.setPossibleMode("CRUDE");
		daoHelper.getDao(Privilege.class).saveOrUpdate(privilege3);

	}
}
